﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Opennav.MapGenerator.Geometry
{
    public class Multipolygon
    {
        public Multipolygon(Polygon[] outerBounds, Polygon[] innerBounds)
        {
            _innerBounds = innerBounds;
            _outerBounds = outerBounds;
            UpdateBounds(_innerBounds);
            UpdateBounds(_outerBounds);
        }

        public Polygon[] Outer
        {
            get
            {
                return _outerBounds;
            }
        }

        public Polygon[] Inner
        {
            get
            {
                return _innerBounds;
            }
        }

        public bool Contains(int longitude, int latitude)
        {
            return Contains(new Coordinate(longitude, latitude));
        }

        public bool Contains(Coordinate coordinate)
        {
            if (coordinate.Longitude < _minLon || coordinate.Longitude > _maxLon || coordinate.Latitude < _minLat || coordinate.Latitude > _maxLat)
                return false;
            bool contains = false;
            if (_outerBounds == null)
            {
                if (_innerBounds == null)
                    return false;
                contains = true;
            }
            else
            {
                foreach (Polygon outer in _outerBounds)
                {
                    if (outer.Contains(coordinate))
                        contains = true;
                }
            }
            if (!contains)
                return false;
            if (_innerBounds != null)
            {
                foreach (Polygon inner in _innerBounds)
                {
                    if (inner.Contains(coordinate))
                        return false;
                }
            }
            return true;
        }

        public bool Contains(Polygon polygon, int probes = 3)
        {
            bool contains = false;
            if (_outerBounds == null)
            {
                if (_innerBounds == null)
                    return false;
                contains = true;
            }
            else
            {
                foreach (Polygon outer in _outerBounds)
                {
                    if (outer.Contains(polygon, probes))
                        contains = true;
                }
            }
            if (!contains)
                return false;
            if (_innerBounds != null)
            {
                foreach (Polygon inner in _innerBounds)
                {
                    if (polygon.Contains(inner, probes))
                        return false;
                }
            }
            return true;
        }

        public bool Contains(Multipolygon other, int probes = 3)
        {
            // otherInners wird erstmal ignoriert
            if (_outerBounds == null || _outerBounds.Length == 0)
                return false;
            foreach (Polygon outer in other.Outer)
            {
                if (!Contains(outer, probes))
                    return false;
            }
            return true;
        }

        #region Private implementation

        private Polygon[] _innerBounds, _outerBounds;

        private int _minLat = int.MaxValue, _maxLat = int.MinValue, _minLon = int.MaxValue, _maxLon = int.MinValue;

        private void UpdateBounds(Polygon[] bounds)
        {
            if (bounds == null)
                return;
            foreach (Polygon polygon in bounds)
            {
                foreach (Coordinate c in polygon.Coordinates)
                {
                    if (_minLat > c.Latitude) _minLat = c.Latitude;
                    else if (_maxLat < c.Latitude) _maxLat = c.Latitude;
                    if (_minLon > c.Longitude) _minLon = c.Longitude;
                    else if (_maxLon < c.Longitude) _maxLon = c.Longitude;
                }
            }
        }

        #endregion
    }

}
